package utils.parser;

//import static entities.vocabulary.QueryKeywords.ORDERING_FEATURE;
//import static entities.vocabulary.QueryKeywords.ORDERING_PARTITION;
//import static entities.vocabulary.QueryKeywords.ORDERING_UN;
import static option.KBVocabulary.LEFTDEL;
import static option.KBVocabulary.RIGHTDEL;
import static option.KBVocabulary.ROLE;
import static option.QueryKeywords.Od_Feat;
import static option.QueryKeywords.Od_Noop;
import static option.QueryKeywords.Od_Oid;
import static option.QueryKeywords.Od_Part;
//import static option.QueryKeywords.Od_Subsume;

import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import option.QueryKeywords;

import kb.DescriptionLogicsKB;
import kb.KBStat;
import kb.RBox;
import entities.Individual;
import entities.assertion.Assertion;
import entities.assertion.ConceptAssertion;
import entities.assertion.RoleAssertion;
import entities.axiom.EquivalenceAxiom;
import entities.axiom.FeatureDomainAxiom;
import entities.axiom.InclusionAxiom;
import entities.axiom.RoleInclusionAxiom;
import entities.axiom.RoleInverseAxiom;
import entities.axiom.RoleTransitiveAxiom;
import entities.concept.AndConcept;
import entities.concept.Concept;
import entities.concept.DomainConcept;
import entities.concept.DomainConceptEQ;
import entities.concept.DomainConceptLT;
import entities.concept.DomainConceptLTEQ;
import entities.concept.ExistsConcept;
import entities.concept.Nominal;
import entities.concept.NotConcept;
import entities.concept.OrConcept;
import entities.concept.PConcept;
import entities.concept.UniversalConcept;
import entities.role.Role;

import utils.Util;
import utils.exception.SyntaxParsingException;
import algebra.query.od.OrderDep;
import algebra.query.od.OrderDepFeature;
import algebra.query.od.OrderDepNoop;
import algebra.query.od.OrderDepOid;
import algebra.query.od.OrderDepPart;
import algebra.query.pd.PdConcept;
import algebra.query.pd.PdConjunction;
import algebra.query.pd.PdFeature;
import algebra.query.pd.PdRole;
import algebra.query.pd.ProjDesc;

public final class Creator {

	public static ProjDesc getPdFromString(String pd, DescriptionLogicsKB kb)
			throws SyntaxParsingException {
		return Creator.createProjDesc(Parser
				.getListOfTokensFromTokenizer(pd), kb);
	}

	public static OrderDep getOdFromString(String ods)
			throws SyntaxParsingException {
		return Creator.createOrderDep(Parser.getListOfTokensFromTokenizer(ods));
	}

	public static InclusionAxiom createInclusionAxiom(LinkedList<String> in,
			DescriptionLogicsKB kb) throws SyntaxParsingException {
		StringBuffer ax = new StringBuffer();
		for (String s : in) {
			ax.append(s);
		}
		Concept lhs = null, rhs = null;
		int count = 0;
		int sides = 2;
		LinkedList<String> sub = new LinkedList<String>();
		while (!in.isEmpty()) {
			String tk = in.removeFirst();
			if (tk == null) {
				System.out.println("Null concpet found in " + in);
				throw new SyntaxParsingException();
			}
			if (sides <= 0) {
				// extra tokens found after parsing LHS and RHS
				System.out.println("Concepts found after creating inclusions: "
						+ ax);
				throw new SyntaxParsingException();
			}
			if (tk.equals(LEFTDEL)) {
				count++;
			} else if (tk.equals(RIGHTDEL)) {
				count--;
			}
			sub.add(tk);
			if (count == 0) {
				// one concept found
				sides--;
				if (sides == 1) {
					// assume LHS comes first
					lhs = Parser.conParser(sub, kb);
				} else if (sides == 0) {
					rhs = Parser.conParser(sub, kb);
				} else {
					System.out
							.println("Wrong # of concepts found in inclusions: check the syntax.");
					throw new SyntaxParsingException();
				}
				sub.clear();
			}

		}
		// if(rhs == null){
		// System.err.println("not parsed count:"+sides + count);
		// }
		if (lhs == null || rhs == null) {
			System.err.println("WARNING! NULL AXIOM: " + rhs);
			throw new SyntaxParsingException();
		}
		return new InclusionAxiom(lhs, rhs);
	}

	// allows for A=B only, no A=B=C etc.
	public static EquivalenceAxiom createEqAxiom(LinkedList<String> in,
			DescriptionLogicsKB kb) throws SyntaxParsingException {
		Concept lhs = null, rhs = null;
		int count = 0;
		int sides = 2;
		LinkedList<String> sub = new LinkedList<String>();
		while (!in.isEmpty()) {
			String tk = in.removeFirst();
			if (tk.equals(LEFTDEL)) {
				count++;
			} else if (tk.equals(RIGHTDEL)) {
				count--;
			}
			sub.add(tk);
			if (count == 0) {
				// one concept found
				sides--;
				if (sides == 1) {
					// assume LHS comes first
					lhs = Parser.conParser(sub, kb);
				} else if (sides == 0) {
					rhs = Parser.conParser(sub, kb);
				} else {
					System.err
							.println("Wrong # of concepts found in equivalent axioms: check the syntax.");
					throw new SyntaxParsingException();
				}
				sub.clear();
			}
		}
		return new EquivalenceAxiom(lhs, rhs);
	}

	private static Object getStringOrRole(LinkedList<String> sub, DescriptionLogicsKB kb)
			throws SyntaxParsingException {
		Object ret = null;
		if (sub.size() > 1) {
			// not a string, a role
			ret = createRole(sub, kb);
		} else if (sub.size() == 1) {
			ret = (String) sub.iterator().next();
		} else {
			System.out
					.println("Error in syntax: only feature or string allowed in feature concepts!");
		}
		return ret;
	}

	public static NotConcept createNotConcept(LinkedList<String> in, DescriptionLogicsKB kb)
			throws SyntaxParsingException {
		return new NotConcept(Parser.conParser(in, kb));
	}

	public static UniversalConcept createUniversalConcept(
			LinkedList<String> in, DescriptionLogicsKB kb) throws SyntaxParsingException {
		if (in.peek() == null) {
			System.out.println("Empty list of tokens, please check!");
			throw new SyntaxParsingException();
		}
		Role r = null;
		Concept filler = null;
		int count = 0;
		LinkedList<String> sub = new LinkedList<String>();
		// get the role
		String tk = null;
		while (!in.isEmpty()) {
			tk = in.peek();
			if (tk.equals(LEFTDEL)) {
				count++;
			} else if (tk.equals(RIGHTDEL)) {
				count--;
			}
			sub.add(tk);
			in.remove();
			if (count == 0) {
				// one concept found
				r = createRole(sub, kb);
				sub.clear();
				break;
			}
		}
		// find the filler
		filler = Parser.conParser(in, kb);
		return new UniversalConcept(r, filler);
	}

	/*
	 * The same as OR concepts
	 */
	public static OrConcept createOrConcept(LinkedList<String> in, DescriptionLogicsKB kb)
			throws SyntaxParsingException {
		int count = 0;
		HashSet<Concept> cons = new HashSet<Concept>();
		LinkedList<String> sub = new LinkedList<String>();
		while (!in.isEmpty()) {
			String tk = in.removeFirst();
			if (tk.equals(LEFTDEL)) {
				count++;
			} else if (tk.equals(RIGHTDEL)) {
				count--;
			}
			sub.add(tk);
			if (count == 0) {
				// one concept found
				cons.add(Parser.conParser(sub, kb));
				sub.clear();
			}
		}
		return new OrConcept(cons);
	}

	// note: a nominal can be (nom a) or (nom a b ...), in the latter we create
	// multiple nominals
	public static Concept createNominalConcept(LinkedList<String> in,
			DescriptionLogicsKB kb) throws SyntaxParsingException {
		if (in.peek() == null) {
			System.out.println("Empty list of tokens, please check!");
			throw new SyntaxParsingException();
		}
		String tk = null;
		Set<Concept> noms = new HashSet<Concept>();
		while (!in.isEmpty()) {
			tk = in.peek();
			noms.add(Nominal.getNominal(tk, false));
			in.remove();
		}
		if (noms.size() == 1) {
			return noms.iterator().next();
		} else if (noms.size() > 1) {
			return new OrConcept(noms);
		} else {
			throw new SyntaxParsingException(
					"Nominals must have at least one name.");
		}
	}

	// some R.C
	public static ExistsConcept createExistsConcept(LinkedList<String> in,
			DescriptionLogicsKB kb) throws SyntaxParsingException {
		if (in.peek() == null) {
			System.out.println("Empty list of tokens, please check!");
			throw new SyntaxParsingException();
		}
		Role r = null;
		Concept filler = null;
		int count = 0;
		LinkedList<String> sub = new LinkedList<String>();
		// get the role
		String tk = null;
		while (!in.isEmpty()) {
			tk = in.peek();
			if (tk.equals(LEFTDEL)) {
				count++;
			} else if (tk.equals(RIGHTDEL)) {
				count--;
			}
			sub.add(tk);
			in.remove();
			if (count == 0) {
				// one concept found
				r = createRole(sub, kb);
				sub.clear();
				break;
			}
		}
		// find the filler
		filler = Parser.conParser(in, kb);
		return new ExistsConcept(r, filler);
	}

	// and (D) (D) etc.
	public static AndConcept createAndConcept(LinkedList<String> in, DescriptionLogicsKB kb)
			throws SyntaxParsingException {
		int count = 0;
		HashSet<Concept> cons = new HashSet<Concept>();
		LinkedList<String> sub = new LinkedList<String>();
		while (!in.isEmpty()) {
			String tk = in.removeFirst();
			if (tk.equals(LEFTDEL)) {
				count++;
			} else if (tk.equals(RIGHTDEL)) {
				count--;
			}
			sub.add(tk);
			if (count == 0) {
				// one concept found
				cons.add(Parser.conParser(sub, kb));
				sub.clear();
			}
		}
		return new AndConcept(cons);
	}

	public static Assertion createConceptAssertion(LinkedList<String> in,
			DescriptionLogicsKB kb) throws SyntaxParsingException {
		if (in.peek() == null) {
			System.out.println("Empty list of tokens, please check!");
			throw new SyntaxParsingException();
		}
		Individual a = null;
		Concept c = null;
		int ind = 0;
		// int count =0;
		boolean done = false;
		String tk = null;
		LinkedList<String> sub = new LinkedList<String>();
		while (!in.isEmpty()) {
			tk = in.remove();
			// if(tk.equals(LEFTDEL) ){
			// count ++;
			// }else if(tk.equals(RIGHTDEL)){
			// count --;
			// }
			switch (ind) {
			case 0:
				a = Individual.newIndividual(tk);
				ind++;
				break;
			case 1:
				sub.add(tk);
				sub.addAll(in);
				done = true;
				break;
			default:
				break;
			}
			if (done) {
				break;
			}
		}
		c = Parser.conParser(sub, kb);
		if (kb!=null && kb.getKBStat() != null) {
			// check if a:A
			Parser.estimateSizeofCp(c, kb.getKBStat());
			// determine if a mentions any feature
			for (Role f : c.extractFeatures()) {
				kb.getKBStat().incFCounts(f);
			}
		}
		return new ConceptAssertion(a, c);
	}

	public static Assertion createRoleAssertion(LinkedList<String> in,
			DescriptionLogicsKB kb) throws SyntaxParsingException {
		if (in.peek() == null) {
			System.out.println("Empty list of tokens, please check: " + in);
			throw new SyntaxParsingException();
		}
		Role r = null;
		Individual a = null, b = null;
		int count = 0;
		boolean done = false;
		int ind = 0;
		String tk = null;
		LinkedList<String> sub = new LinkedList<String>();
		while (!in.isEmpty()) {
			tk = in.remove();
			if (tk.equals(LEFTDEL)) {
				count++;
			} else if (tk.equals(RIGHTDEL)) {
				count--;
			}
			switch (ind) {
			case 0:
				a = Individual.newIndividual(tk);
				// System.out.println("creates ind:"+tk);
				ind++;
				break;
			case 1:
				b = Individual.newIndividual(tk);
				// System.out.println("creates ind:"+tk);
				ind++;
				break;
			case 2:
				if (count != 0) {
					sub.add(tk);
					sub.addAll(in);
					done = true;
				} else {
					System.err
							.println("Brackets do not match in role assertion.");
					throw new SyntaxParsingException();
				}
				break;
			default:
				break;
			}
			;

			if (done) {
				break;
			}
		}
		r = createRole(sub, kb);
		if (kb.getKBStat() != null) {
			kb.getKBStat().incRoleCounts(r);
		}
		return new RoleAssertion(a, b, r);

	}

	public static OrderDep createOrderDep(LinkedList<String> tokens)
			throws SyntaxParsingException {
		String head = tokens.peek();
		if (!head.equalsIgnoreCase(LEFTDEL)) {
			throw new SyntaxParsingException("Malformed Order Dependecy: "
					+ tokens);
		} else
			while (tokens.peek().equalsIgnoreCase(LEFTDEL)) {
				tokens.remove();
				tokens.removeLast();
			}
		head = tokens.poll();
		if (head.equalsIgnoreCase(Od_Noop)) {
			// ignore the rest tokens as noop does not have sub Ods.
			return new OrderDepNoop();
		} else if (head.equalsIgnoreCase(Od_Oid)) {
			// Oid:od
			return new OrderDepOid();
		} else if (head.equalsIgnoreCase(Od_Feat)) {
			// Oid:od
			List<LinkedList<String>> subs = Parser
					.breakListByMatchingBrackets(tokens);
			if (subs.size() == 2) {
				String fs = Parser.tokensAsString(subs.get(0));
				Role f = Role.createRoleAsIs(fs);
				OrderDep sub = createOrderDep(subs.get(1));
				return new OrderDepFeature(f, sub);
			} else {
				throw new SyntaxParsingException("(" + Od_Feat
						+ " feature_name Od) expected: " + subs);
			}
		} else if (head.equalsIgnoreCase(Od_Part)) {
			// C (Od1) (Od2)
			List<LinkedList<String>> subs = Parser
					.breakListByMatchingBrackets(tokens);
			if (subs.size() == 3) {
				Concept pc = Parser.conParser(subs.get(0), null);
				OrderDep sub1 = createOrderDep(subs.get(1));
				OrderDep sub2 = createOrderDep(subs.get(2));
				return new OrderDepPart(pc, sub1, sub2);
			} else {
				throw new SyntaxParsingException("(" + Od_Part + " C Od1 Od2"
						+ ") expected.");
			}
		} 
//		else if (head.equalsIgnoreCase(Od_Subsume)) {
//			List<LinkedList<String>> subs = Parser
//					.breakListByMatchingBrackets(tokens);
//			if (subs.size() == 1) {
//				OrderDep sub1 = createOrderDep(subs.get(0));
//				return new OrderDepSub(sub1);
//			} else {
//				throw new SyntaxParsingException("(" + Od_Subsume
//						+ " Od) expected.");
//			}
//		} 
		else {
			throw new SyntaxParsingException("Malformed Order Dependecy: "
					+ head);
		}
		// return null;
	}

	public static ProjDesc createProjDesc(
			LinkedList<String> tokens, DescriptionLogicsKB kb) throws SyntaxParsingException {
		String head = tokens.peek();
		if (!head.equalsIgnoreCase(LEFTDEL)) {
			throw new SyntaxParsingException("Malformed Order Dependecy: "
					+ tokens);
		} else
			while (tokens.peek().equalsIgnoreCase(LEFTDEL)) {
				tokens.remove();
				tokens.removeLast();
			}
		head = tokens.poll();
		if (head.equalsIgnoreCase(QueryKeywords.PD_FEATURE)) {
			String f = tokens.poll().trim();
			if(f.equalsIgnoreCase(RIGHTDEL)){
				throw new SyntaxParsingException("Pd feature name required:" + tokens);
			}
			Role rf = Role.createRoleAsIs(f);
			return new PdFeature(rf);
		} else if (head.equalsIgnoreCase(QueryKeywords.PD_CONCEPT)) {
			List<LinkedList<String>> subs = Parser
					.breakListByMatchingBrackets(tokens);
			if(subs.size() != 1){
				throw new SyntaxParsingException("Pd concept parsing error:" + tokens);
			}
			Concept cp = Parser.conParser(subs.get(0), kb);
			return new PdConcept(cp);
		} else if (head.equalsIgnoreCase(QueryKeywords.PD_ROLE)) {
			// Oid:od
			List<LinkedList<String>> subs = Parser
					.breakListByMatchingBrackets(tokens);
			if (subs.size() == 2) {
				String fs = Parser.tokensAsString(subs.get(0));
				Role f = Role.createRoleAsIs(fs);
				ProjDesc sub = createProjDesc(subs.get(1), kb);
				return new PdRole(f, sub);
			} else {
				throw new SyntaxParsingException("Pd Role parsing error: " + tokens);
			}
		} else if (head.equalsIgnoreCase(QueryKeywords.PD_CONJUNCTION)) {
			// C (Od1) (Od2)
			List<LinkedList<String>> subs = Parser
					.breakListByMatchingBrackets(tokens);
			if (subs.size() == 2) {
				ProjDesc sub1 = createProjDesc(subs.get(0), kb);
				ProjDesc sub2 = createProjDesc(subs.get(1), kb);
				return new PdConjunction(sub1, sub2);
			} else {
				throw new SyntaxParsingException("Pd And parsing error: "+tokens);
			}
		} 
		else {
			throw new SyntaxParsingException("Malformed Projection Desc: "
					+ head);
		}
	}

	public static PConcept createPConcept(String pc) {
		return PConcept.getPConcept(pc);
	}

	// (role r) only
	public static Role createRole(LinkedList<String> in, DescriptionLogicsKB kb)
			throws SyntaxParsingException {
		Role r = null;
		if (in.peek() == null) {
			throw new SyntaxParsingException("Empty list of tokens, please check!");
		}
		while (!in.isEmpty()) {
			String tk = in.removeFirst();
			if (tk.equals(LEFTDEL)) {
				in.removeLast();
			} else if (tk.equals(ROLE)) {
				// the next would be a role or a role inclusion
				// sub.addAll(in);
				String rs = in.removeFirst();
				if (!in.isEmpty()) {
					// syntax error, no role path supported yet
					throw new SyntaxParsingException
					("The syntax for role is wrong. Extra chars ignored: "
									+ rs);
				}
				RBox rb = null;
				KBStat stat = null;
				if(kb!=null){
					rb = kb.getTbox().getRoleBox();
					stat = kb.getKBStat();
				}
				r = Role.createRole(rs, rb);
				if (stat != null) {
					stat.addEntityNames(rs, "role");
				}
				break;
			}
		}
		return r;
	}

	// (? (role r) "v"); 0 for =, -1 for <, 1 for >
	public static DomainConcept<?, ?> createDomainConcept(
			LinkedList<String> in, int type, DescriptionLogicsKB kb)
			throws SyntaxParsingException {
		Object lhs = null;
		Object rhs = null;
		DomainConcept<?, ?> dc = null;
		int count = 0;
		boolean left = true;
		LinkedList<String> sub = new LinkedList<String>();
		while (!in.isEmpty()) {
			String tk = in.removeFirst();
			if (tk.equals(LEFTDEL)) {
				count++;
			} else if (tk.equals(RIGHTDEL)) {
				count--;
			}
			sub.add(tk);
			if (count == 0) {
				if (left) {
					// get the left hand side
					lhs = getStringOrRole(sub, null);
				} else {
					// the right hand side
					rhs = getStringOrRole(sub, null);
				}
				sub.clear();
				left = false;
			}
		}
		KBStat stat = null;
		if(kb!=null){
			stat = kb.getKBStat();
		}
		// get a list of constants and features
		if (lhs instanceof String) {
			Util.addKBConstants((String) lhs);
		} else if (stat != null) {
			stat.incNumFeatures();
			stat.addEntityNames(((Role) lhs).getRoleName(), "feature");
		}
		if (rhs instanceof String) {
			Util.addKBConstants((String) rhs);
		} else if (stat != null) {
			stat.incNumFeatures();
			stat.addEntityNames(((Role) rhs).getRoleName(), "feature");
		}
		// get stat of features (only for f=k or f<=k)
		if (type >= 0 && stat != null) {
			if (lhs instanceof Role && rhs instanceof String) {
				stat.setFValues((Role) lhs, (String) rhs);
			} else if (lhs instanceof String && rhs instanceof Role) {
				stat.setFValues((Role) rhs, (String) lhs);
			}
		}
		//
		switch (type) {
		case 0:
			dc = new DomainConceptEQ<Object, Object>(lhs, rhs);
			break;
		case -1:
			dc = new DomainConceptLT<Object, Object>(lhs, rhs);
			break;
		case 1:
			dc = new DomainConceptLTEQ<Object, Object>(lhs, rhs);
			break;
		}
		return dc;
	}

	public static RoleInclusionAxiom createRoleIncAxiom(LinkedList<String> tokens,
			DescriptionLogicsKB kb) throws SyntaxParsingException {
		Role rl = null, rr = null;
		List<LinkedList<String>> two  = Parser.breakListByMatchingBrackets(tokens);
		if(two.size()!=2){
			throw new SyntaxParsingException("Role inclusions must include two roles.");
		}
		rl = Creator.createRole(two.get(0), kb);
		rr = Creator.createRole(two.get(1), kb);
		return new RoleInclusionAxiom(rl, rr);
	}
	
	public static RoleTransitiveAxiom createRoleTransitiveAxiom(LinkedList<String> tokens,
			DescriptionLogicsKB kb) throws SyntaxParsingException {
		Role tr = null;
		tr = Creator.createRole(tokens, kb);
		return new RoleTransitiveAxiom(tr);
	}
	
	public static RoleInverseAxiom createRoleInverseAxiom(LinkedList<String> tokens,
			DescriptionLogicsKB kb) throws SyntaxParsingException {
		Role rl = null, rr = null;
		List<LinkedList<String>> two  = Parser.breakListByMatchingBrackets(tokens);
		if(two.size()!=2){
			throw new SyntaxParsingException("Role inverse must include two roles.");
		}
		rl = Creator.createRole(two.get(0), kb);
		rr = Creator.createRole(two.get(1), kb);
		return new RoleInverseAxiom(rl, rr);
	}
	
	public static FeatureDomainAxiom createFeatureDomAxiom(LinkedList<String> tokens,
			DescriptionLogicsKB kb) throws SyntaxParsingException {
		Role f = null;
		Concept d = null;
		List<LinkedList<String>> two  = Parser.breakListByMatchingBrackets(tokens);
		if(two.size()!=2){
			throw new SyntaxParsingException("Feature domain declaration must have a feature and a concept.");
		}
		f = Creator.createRole(two.get(0), kb);
		d = Parser.conParser(two.get(1), kb);
		return new FeatureDomainAxiom(f, d);
	}

	// public static OrderingDescription
	// createOrderingDescription(LinkedList<String> tokens)
	// throws SyntaxParsingException{
	// OrderingDescription od = null;
	// try {
	// od = new OrderingDescription("");
	// } catch (OrderingDescriptionException e) {
	// e.printStackTrace();
	// }
	// String head = tokens.peek();
	// if(head.equalsIgnoreCase(LEFTDEL)){
	// tokens.remove();
	// tokens.removeLast();
	// }
	// head = tokens.poll();
	// if(head.equalsIgnoreCase(ORDERING_UN) || head.equalsIgnoreCase("(un)")){
	// od.setType(ORDERING_UN);
	// }else if(head.equalsIgnoreCase(ORDERING_FEATURE)){
	// //f, Od
	// od.setType(ORDERING_FEATURE);
	// List<LinkedList<String>> subs =
	// Parser.breakListByMatchingBrackets(tokens);
	// if(subs.size() != 2){
	// //likely it is (od-feature f un)
	// // LinkedList<String> one = subs.get(0);
	// // if(one.contains("un") || one.contains("Un")){
	// // int i = one.indexOf("un");
	// // i = i >= 0? i: one.indexOf("Un");
	// // int j = one.size()-1;
	// // for(; j>=i ;j--){
	// // one.remove(j);
	// // }
	// // od.arg = tokensAsString(one);
	// // LinkedList<String> lun = new LinkedList<String>();
	// // lun.add("(un)");
	// // od.residualOd = createOrderingDescription(lun,kb);
	// // }else{
	// // System.out.println("(f, Od) expected");
	// // throw new SyntaxParsingException();
	// // }
	// System.out.println("Malformed Partition Ordering Description: "+subs);
	// throw new SyntaxParsingException();
	// }else if(subs.size()==2){
	// od.arg = Parser.tokensAsString(subs.get(0));
	// od.residualOd = createOrderingDescription(subs.get(1));
	// }else{
	//
	// }
	// }else if(head.equalsIgnoreCase(ORDERING_PARTITION)){
	// //C (Od1 Od2)
	// od.setType(ORDERING_PARTITION);
	// List<LinkedList<String>> subs =
	// Parser.breakListByMatchingBrackets(tokens);
	// if(subs.size() != 2){
	// System.out.println("(f, Od) expected.");
	// throw new SyntaxParsingException();
	// }else{
	// od.partition = Parser.conParser(subs.get(0), null);
	// LinkedList<String> ods = subs.get(1);
	// if(! ods.peek().equalsIgnoreCase(LEFTDEL)){
	// System.out.println("Malformed Partition Ordering Description.");
	// throw new SyntaxParsingException();
	// }
	// ods.remove();
	// ods.removeLast();
	// subs = Parser.breakListByMatchingBrackets(ods);
	// if(subs.size() != 2){
	// System.out.println("(f, Od) expected.");
	// throw new SyntaxParsingException();
	// }else{
	// od.residualOd = createOrderingDescription(subs.get(0));
	// od.residualOd2 = createOrderingDescription(subs.get(1));
	// }
	// }
	// }
	// return od;
	// }

}
